# 回测管理系统
# 每天/每个tick文件都重新生成一遍各个组件，最大程度确保兼容实盘
from core.PublicContext import PublicContext
from core.Logger import Logger
from core.StrategyManager import StrategyManager
from MockTrader import MockTrader
from core.RawMDProcessor import RawMDProcessor
from TestStrategy import TestStrategy
from LocalTickLoader import LocalTickLoader
import time


class BacktestManager:
    market_value_sequence = {}
    backtest_data_files = []
    strategies_initer = []
    portfolio = {}

    def __init__(self, backtest_data_files, portfolio):
        self.backtest_data_files = backtest_data_files
        self.portfolio = portfolio

    def start_back_test(self):
        # 创建空的log文件
        with open('./log.txt', 'w', encoding='utf-8') as f:
            f.write('Back test started.')

        # 开始对每个行情文件回测
        for data_file in self.backtest_data_files:
            # 记录文件名称
            with open('./log.txt', 'a', encoding='utf-8') as f:
                f.write('\n\n---> Back testing [{}]\n\n'.format(data_file))
            # 执行回测
            print('\n\n---->Start backtesting {}'.format(data_file))
            self.backtest_single_file(data_file)

    def backtest_single_file(self, data_file):
        # 创建PublicContext
        public_context = PublicContext('syn')

        # 创建logger
        logger = Logger('./log.txt', 'a')
        public_context.logger = logger
        logger.public_context = public_context
        logger.start()
        logger.log_message('Logger started.')

        # 创建策略管理器
        strategy_manager = StrategyManager()
        strategy_manager.public_context = public_context

        # 创建Trader
        trader = MockTrader()
        trader.initialize(self.portfolio)
        trader.public_context = public_context
        trader.strategy_manager = strategy_manager
        public_context.trader = trader
        trader.start()

        # raw_md_listener: 中转原始行情
        raw_md_listener = RawMDProcessor()
        raw_md_listener.public_context = public_context
        raw_md_listener.stg_manager = strategy_manager

        # 新建策略实例
        for strategy in self.strategies_initer:
            strategy_manager.register_strategy(strategy())

        # 初始化策略
        strategy_manager.initialize()

        # ----------------------------
        # 准备工作完成，开始从文件中加载行情
        local_md_loader = LocalTickLoader()
        local_md_loader.set_data_path(data_file)
        local_md_loader.set_md_queue(raw_md_listener.raw_md_queue)

        # 开启行情线程
        raw_md_listener.start()
        local_md_loader.start()

        # 等待今日行情结束
        while True:
            if public_context.get_current_time() < "15:05:00":
                time.sleep(1)
                continue
            break

        # 通知各个组件退出
        raw_md_listener.finish()
        trader.finish()
        logger.finish()
        # 打印信息
        print('\n--> Clearing info for {}'.format(data_file))
        trader.print_orders()
        print(trader.portfolio)
        print(trader.get_market_value())
        # 更新当前持仓，记录净值
        trader.clearing()
        self.portfolio = trader.portfolio
        self.market_value_sequence[data_file] = trader.get_market_value()

